﻿#include "sys_plat.h"
#include "socket.h"
#include "debug.h"
#include "sock.h"
#include "exmsg.h"

/**
 * @brief 将ip地址转化为字符串
 * @param in ip地址
 * @return 字符串形式的ip地址
 */
char *x_inet_ntoa(struct x_in_addr in)
{
    static char ip_str[IPV4_ADDR_STR_SIZE];
    plat_memset(ip_str, 0, IPV4_ADDR_STR_SIZE);
    plat_sprintf(ip_str, "%d.%d.%d.%d", in.addr_0, in.addr_1, in.addr_2, in.addr_3);
    return ip_str;
}

/**
 * @brief 将字符串转换为特定格式的ip地址
 * @param str 字符串形式的ip地址
 * @return 以32bit表示的ip地址
 */
uint32_t x_inet_addr(const char *str)
{
    if (!str)
        return INADDR_ANY;
    ipaddr_t ipaddr;
    ipaddr_from_str(&ipaddr, str);

    return ipaddr.q_addr;
}

/**
 * @brief 将ip地址从字符串格式转换为网络地址格式
 * @param family 协议类型
 * @param strprt 字符串形式的ip地址
 * @param addrptr 转换后的ip地址
 */
int x_inet_pton(int family, const char *strptr, void *addrptr)
{
    if (family != AF_INET || !strptr || !addrptr)
        return -1;

    struct x_in_addr *addr = (struct x_in_addr *)addrptr;
    ipaddr_t ipaddr;
    ipaddr_from_str(&ipaddr, strptr);
    addr->s_addr = ipaddr.q_addr;

    return 0;
}

/**
 * @brief 将ip地址从网络地址格式转换为字符串
 * @param family 协议类型
 * @param addrptr 网络地址格式的ip地址
 * @param strptr 字符串形式的ip地址
 * @param len  字符串长度
 */
const char *x_inet_ntop(int family, const void *addrptr, char *strptr, size_t len)
{
    if (family != AF_INET || !strptr || !addrptr)
        return NULL;

    struct x_in_addr *addr = (struct x_in_addr *)addrptr;
    char buf[IPV4_ADDR_STR_SIZE];
    plat_memset(buf, 0, IPV4_ADDR_SIZE);
    plat_sprintf(buf, "%d.%d.%d.%d", addr->addr_0, addr->addr_1, addr->addr_2, addr->addr_3);
    plat_strcpy(strptr, buf);

    return strptr;
}

/**
 * @brief 创建socket
 * @param family IP协议类型
 * @param type 套接字类型
 * @param protocol 传输协议类型
 */
int x_socket(int family, int type, int protocol)
{
    // 初始化参数，交给核心工作线程处理
    sock_req_t req;
    req.create.family = family;
    req.create.type = type;
    req.create.protocol = protocol;
    req.wait = NULL;
    req.wait_tmo = 0;
    net_err_t err = exmsg_func_exec(sock_create_req_in, &req);
    if (err < NET_ERR_OK)
    {
        DBG_ERROR(DBG_SOCKET_LEVEL, "create socket failed!");
        return -1;
    }

    return req.sockfd;
}

/**
 * @brief 向外发送数据
 * @param s socket序号
 * @param buf 需要发送的消息
 * @param len 消息长度
 * @param flags 标志位
 * @param dest 目的地址
 * @param dest_len 目的地址长度
 */
ssize_t x_sendto(int s, const void *buf, size_t len, int flags, const struct x_sockaddr *dest, x_socklen_t dest_len)
{
    // 参数检查
    if (!buf || !len)
    {
        DBG_ERROR(DBG_SOCKET_LEVEL, "send message is error!");
        return -1;
    }
    if (sizeof(struct x_sockaddr) != dest_len)
    {
        DBG_ERROR(DBG_SOCKET_LEVEL, "dest addr len and dest_len is no equal!");
        return -1;
    }
    if (dest->sin_family != AF_INET)
    {
        DBG_ERROR(DBG_SOCKET_LEVEL, "the family:%d dosen't support!");
        return -1;
    }

    uint8_t *start = (uint8_t *)buf; // 记录数据发送的起始位置
    ssize_t send_size = 0;           // 记录已经发送了多少数据
    while (len > 0)
    {
        sock_req_t send_req;
        send_req.sockfd = s;
        send_req.data.addr = (struct x_sockaddr_in *)dest;
        send_req.data.len = len;
        send_req.data.buf = start;
        send_req.data.flags = flags;
        send_req.data.addr_len = (x_socklen_t *)&dest_len;
        send_req.data.comply = 0;
        send_req.wait = NULL;
        send_req.wait_tmo = 0;

        net_err_t err = exmsg_func_exec(sock_sendto_req_in, &send_req);
        if (err < NET_ERR_OK)
        {
            DBG_ERROR(DBG_SOCKET_LEVEL, "some error have occured in exmsg func!");
            return send_size;
        }

        if (send_req.wait && ((err = sock_wait_enter(send_req.wait, send_req.wait_tmo)) < NET_ERR_OK))
        {
            if (err < NET_ERR_OK)
            {
                DBG_INFO(DBG_SOCKET_LEVEL, "send fialed! sock enter wait!");
                return -1;
            }
        }

        len -= send_req.data.comply;
        start += send_req.data.comply;
        send_size += (ssize_t)send_req.data.comply;
    }

    return send_size;
}

/**
 * @brief 应用程序调用的send接口
 */
ssize_t x_send(int s, const void *buf, size_t len, int flags)
{
    if (!buf || !len)
    {
        return -1;
    }

    uint8_t *start = (uint8_t *)buf; // 记录数据发送的起始位置
    ssize_t send_size = 0;           // 记录已经发送了多少数据
    while (len > 0)
    {
        sock_req_t send_req;
        send_req.sockfd = s;
        send_req.data.addr = NULL;
        send_req.data.len = len;
        send_req.data.buf = start;
        send_req.data.flags = flags;
        send_req.data.addr_len = 0;
        send_req.data.comply = 0;
        send_req.wait = NULL;
        send_req.wait_tmo = 0;

        net_err_t err = exmsg_func_exec(sock_send_req_in, &send_req);
        if (err < NET_ERR_OK)
        {
            DBG_ERROR(DBG_SOCKET_LEVEL, "some error have occured in exmsg func!");
            return send_size;
        }

        if (send_req.wait && ((err = sock_wait_enter(send_req.wait, send_req.wait_tmo)) < NET_ERR_OK))
        {
            if (err < NET_ERR_OK)
            {
                DBG_INFO(DBG_SOCKET_LEVEL, "send fialed! sock enter wait!");
                return -1;
            }
        }

        len -= send_req.data.comply;
        start += send_req.data.comply;
        send_size += (ssize_t)send_req.data.comply;
    }

    return send_size;
}

ssize_t x_recvfrom(int s, char *buf, int len, int flags, struct x_sockaddr *from, int *fromlen)
{
    // 参数检查
    if (!buf || !len || !from || !fromlen)
    {
        DBG_ERROR(DBG_SOCKET_LEVEL, "send message is error!");
        return -1;
    }

    while (1)
    {
        sock_req_t recv_req;
        recv_req.sockfd = s;
        recv_req.data.addr = (struct x_sockaddr_in *)from;
        recv_req.data.len = len;
        recv_req.data.buf = buf;
        recv_req.data.flags = flags;
        recv_req.data.addr_len = (x_socklen_t *)(fromlen);
        recv_req.data.comply = 0;

        recv_req.wait = NULL;
        recv_req.wait_tmo = 0;

        net_err_t err = exmsg_func_exec(sock_recvfrom_req_in, &recv_req);
        if (err < NET_ERR_OK)
        {
            DBG_ERROR(DBG_SOCKET_LEVEL, "some error have occured in exmsg func!");
            return -1;
        }
        if (recv_req.data.comply)
        {
            return recv_req.data.comply;
        }

        // 函数未调用失败但是收到的数据为0，则认为接收需要等待
        err = sock_wait_enter(recv_req.wait, recv_req.wait_tmo);
        if (err < NET_ERR_OK)
        {
            DBG_INFO(DBG_SOCKET_LEVEL, "recv failed! sock enter wait");
            return -1;
        }
    }

    return -1;
}

/**
 * @brief 应用程序调用的recv接口
 */
ssize_t x_recv(int s, char *buf, int len, int flags)
{
    // 参数检查
    if (!buf || !len)
    {
        DBG_ERROR(DBG_SOCKET_LEVEL, "send message is error!");
        return -1;
    }

    while (1)
    {
        sock_req_t recv_req;
        recv_req.sockfd = s;
        recv_req.data.addr = NULL;
        recv_req.data.len = len;
        recv_req.data.buf = buf;
        recv_req.data.flags = flags;
        recv_req.data.addr_len = NULL;
        recv_req.data.comply = 0;

        recv_req.wait = NULL;
        recv_req.wait_tmo = 0;

        net_err_t err = exmsg_func_exec(sock_recv_req_in, &recv_req);
        if (err < NET_ERR_OK)
        {
            DBG_ERROR(DBG_SOCKET_LEVEL, "some error have occured in exmsg func!");
            return -1;
        }
        if (recv_req.data.comply)
        {
            return recv_req.data.comply;
        }

        // 函数未调用失败但是收到的数据为0，则认为接收需要等待
        err = sock_wait_enter(recv_req.wait, recv_req.wait_tmo);
        if (err < NET_ERR_OK)
        {
            DBG_INFO(DBG_SOCKET_LEVEL, "recv failed! sock enter wait");
            return -1;
        }
    }

    return -1;
}

/**
 * @brief 设置socket例如超时等相关属性，参考linux下setsocketopt函数
 */
int x_setsocketopt(int s, int level, int optname, const char *optval, int len)
{
    if (!optval || !len)
    {
        return -1;
    }

    sock_req_t req;
    req.sockfd = s;
    req.wait = NULL;
    req.wait_tmo = 0;
    req.opt.level = level;
    req.opt.optname = optname;
    req.opt.optval = optval;
    req.opt.len = len;
    net_err_t err = exmsg_func_exec(sock_setsockopt_req_in, &req);
    if (err < NET_ERR_OK)
    {
        DBG_ERROR(DBG_SOCKET_LEVEL, "set sock opt failed!");
        return -1;
    }

    return 0;
}

int x_connect(int s, const struct x_sockaddr *addr, x_socklen_t len)
{
    if (!addr || !len)
    {
        return -1;
    }

    if (addr->sin_family != AF_INET)
    {
        DBG_ERROR(DBG_SOCKET_LEVEL, "the family:%d of addr no support!", addr->sin_family);
        return -1;
    }

    sock_req_t req;
    req.sockfd = s;
    req.wait = NULL;
    req.wait_tmo = 0;
    req.connect.addr = addr;
    req.connect.addrlen = len;

    net_err_t err = exmsg_func_exec(sock_connect_req_in, &req);
    if (err < 0)
    {
        DBG_ERROR(DBG_SOCKET_LEVEL, "socket:%d connect faield!", s);
        return -1;
    }

    return 0;
}

/**
 * @brief 应用调用band函数的时的入口
 */
int x_bind(int s, const struct x_sockaddr *addr, x_socklen_t len)
{
    if (!addr || !len)
    {
        return -1;
    }

    if (addr->sin_family != AF_INET)
    {
        DBG_ERROR(DBG_SOCKET_LEVEL, "the family:%d of addr no support!", addr->sin_family);
        return -1;
    }

    if(sizeof(struct x_sockaddr_in) != len)
    {
        DBG_WARNING(DBG_SOCKET_LEVEL, "the addr len is error!");
        return -1;
    }

    sock_req_t req;
    req.sockfd = s;
    req.wait = NULL;
    req.wait_tmo = 0;
    req.bind.addr = addr;
    req.bind.addrlen = len;

    net_err_t err = exmsg_func_exec(sock_bind_req_in, &req);
    if (err < 0)
    {
        DBG_ERROR(DBG_SOCKET_LEVEL, "socket:%d connect faield!", s);
        return -1;
    }

    return 0;
}

int x_close(int s)
{
    sock_req_t req;
    req.sockfd = s;
    req.wait = NULL;
    req.wait_tmo = 0;
    net_err_t err = exmsg_func_exec(sock_close_req_in, &req);
    if (err < NET_ERR_OK)
    {
        DBG_ERROR(DBG_SOCKET_LEVEL, "close socket failed!");
        return -1;
    }

    return 0;
}